package main_test

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/Jeffail/gabs/v2"
	"github.com/golang-jwt/jwt"
	"github.com/spf13/cast"
)

const (
	ClientID  = "1199473138831"
	PublicKey = "q_dg3yBVgqBvwF8fLiDXoVQJZzq-U_Mzmr2xEVBMs6Y"
	// PrivateKey = "./static/private_key.pem"
)

func RandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(b)
}

func GetToken() string {
	header := map[string]interface{}{
		"alg": "RS256",
		"typ": "JWT",
		"kid": PublicKey,
	}

	// 将头部信息序列化为JSON格式字符串
	headerBytes, err := json.Marshal(header)
	if err != nil {
		fmt.Println("JSON encoding error:", err)
		return ""
	}
	headerStr := base64.RawURLEncoding.EncodeToString(headerBytes)
	// 定义Payload信息
	payload := map[string]interface{}{
		"iss": ClientID,
		"aud": "api.coze.cn",                 //扣子 API 的Endpoint
		"iat": int(time.Now().Unix()),        // 签发时间，表示JWT的签发时间，一般为当前时间的时间戳
		"exp": int(time.Now().Unix()) + 3600, // 过期时间，表示JWT的过期时间，一般为签发时间加上有效期，以秒为单位
		"jti": RandomString(36),              // 随机字符串，长度大于32位
		// "session_name": "1",
	}
	// 将Payload信息序列化为JSON格式字符串
	payloadBytes, err := json.Marshal(payload)
	if err != nil {
		fmt.Println("JSON encoding error:", err)
		return ""
	}
	payloadStr := base64.RawURLEncoding.EncodeToString(payloadBytes)
	// 生成签名
	signingInput := fmt.Sprintf("%s.%s", headerStr, payloadStr)
	privateKeyPEM := `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQo4CxnN7rDGaf
yCro40CyBwcoMrp2FmcXc/R6r2ZDDEY5RY1+8sck3ACaHV/b8IC1xBn4Ep8BSXXD
mjg7drLifn3j6CcApQu1wu8KGkOXe4/3agaV029jQKp6qR2Wd5bGoSlTWb4kMOz4
VjJ3ZMmTxkVi6IR2Wc1J3Q4ODcQ6/f+SkyQg+6DLHrgIQ/5yFiD4QMYtfS+sxjsb
iZrW4puICmxGx2w3dryjvXsLR+BXh3mtZjeB8y8Drd4CdKx3nxOdiGuFH126Hirq
AOhISsk7ypJEsxz2HSMRUGzmkBhFY3xcATbu/EuqjX7TJbjYDIdS0xXkcC7Xm5m0
qVu9uZ1RAgMBAAECggEAI7QQlQddqZTWklOVcAaE1k1Q0XXwPC0chpgLfetlKWDS
xtlp66/fQ7SA+4oLux17kCLXrDpggK9TABVGEzuiPbGuvr70Pb8ADH6RhiNkkvSf
3ZmRBZP7N3tjecLcOGPN1rs6mcYZ3xIqtMSGUZ2R+sXjI960sAhL2hNUoFh6m3rv
Zt9CTpraTG8AZP/Z2OcW98eMg2MfYY/Wgc/ejyGZxEORKk344qrOp9aZFTqxsDBW
r1hik8RebxtQSJNI8iJ9gm7VqxCz7tiMO23r7BPaHPzuSIALm8Vao4eC8Yo4XRBt
5U4zZF+S1M7CfNUE/9B8eTWTIRfW/7J0ew8i5Nl4KQKBgQDKlOTU4kgl4uwcZkmB
ic9/h7Ct9g5IZH0jnn2Em/ktbezPLESqnA+PnYeckxbDip4KKyBQ2VI7TvlWYcBl
WShW0x3fh5Hgw1aboyr/DU/7XhPoIvtQg7P0Vw4hH0MUBKYRxm6qJR+nSrm4oRsZ
EzOSRFBZ3fg83j2Oe0g0nFP4BQKBgQC2xzfwmd8BvBURAK0NrFuNdqGbjXPoWwKh
3vJ2EB64dJAc0x/fzEIJ6FJq5fxCmVbtS2SL2QNIK1RJiMzgZ145Hd5vgg2GFgRt
W3vrdi66pFNSg0lLdvoQj2NemdOi/868oVwyoKfTIy+/xvcbeKUkuYhazhw5qonh
9i/iWYdN3QKBgQDJU53zP4rqNBHoy3LjzPytRkG9MRrSsSN4gatGXegOUP+WiO0Z
DQ2d8bVzUu69mIYlnuR31PKXRI4hXfZiAnBHkXpPyqCcWiU5ebhiT22cZ8uq2REf
3DO8ccP2AOad/1y3r5gNeeVyUZ4vMdUHX4DSLRgZp7Jrc4aDkluZBX+hrQKBgE3E
9ENWZTHKwjfqzrcrqATH/jk+dZve5X7UatvbPgcD6bGqDzzdHxgyFqdPVgdMUVVE
J/LtEl1pukJTh8DPmqK418UgU/rCcX3KWC62qWlWs/E+1Tfb1sinCgPdddQ7/c36
5kzQWLgYl5+E2+1/Ztz6aE8itZW/v006v+MSbuStAoGAZaouufv6pofgScCFp+ES
9jYyjJe3iMmWlFh0sJGHX6bAv6jENexox6yQuIwtRJW0qRPsESw3KeZfl4Gh7yjh
e5h8XpSsrFv7DcmLvz5AJMMcuTP73e0Rja5zWHpDFc8XCtSYkBvQjC9QnnBKt4Ip
t1aP9QbDQER5DD15y4CJOdk=
-----END PRIVATE KEY-----`
	// 加载私钥
	privateKey, err := loadPrivateKey(privateKeyPEM)
	if err != nil {
		log.Fatalf("Failed to load private key: %v", err)
	}
	signature, err := jwt.SigningMethodRS256.Sign(signingInput, privateKey)
	// return signature
	// fmt.Println(signature)
	if err != nil {
		log.Fatalf("Failed to sign JWT: %v", err)
	}
	// signatureBase64 := base64.RawURLEncoding.EncodeToString([]byte(signature))
	// fmt.Println(signatureBase64)
	// 5. 构建完整的 JWT
	jwtToken := fmt.Sprintf("%s.%s.%s", headerStr, payloadStr, signature)
	return jwtToken
}

func loadPrivateKey(privateKeyPEM string) (*rsa.PrivateKey, error) {
	block, _ := pem.Decode([]byte(privateKeyPEM))
	if block == nil {
		return nil, fmt.Errorf("failed to decode PEM block containing private key")
	}

	privateKeyInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, fmt.Errorf("failed to parse PKCS#8 private key: %v", err)
	}

	// 断言为 *rsa.PrivateKey
	privateKey, ok := privateKeyInterface.(*rsa.PrivateKey)
	if !ok {
		return nil, fmt.Errorf("private key is not of type *rsa.PrivateKey")
	}

	return privateKey, nil
}

func HttpBuildQuery2(params map[string]interface{}) (paramStr string) {
	paramsArr := make([]string, 0, len(params))
	for k, v := range params {
		paramsArr = append(paramsArr, fmt.Sprintf("%s=%s", k, cast.ToString(v)))
	}
	paramStr = strings.Join(paramsArr, "&")
	return paramStr
}

func NewCurrencyRequest(method string, url string, params map[string]interface{}, headers map[string]string) ([]byte, error) {
	client := &http.Client{Timeout: 120 * time.Second}
	var paramsStr string
	if method == "GET" || method == "DELETE" {
		paramsStr = HttpBuildQuery2(params)
		if strings.Index(url, "?") > -1 {
			url = url + "&" + paramsStr
		} else {
			url = url + "?" + paramsStr
		}
	} else {
		jsonStr, _ := json.Marshal(params)
		paramsStr = string(jsonStr)
	}
	req, err := http.NewRequest(method, url, strings.NewReader(paramsStr))
	if err != nil {
		return nil, err
	}
	req.Header.Add("Accept", "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
	req.Header.Add("Connection", "keep-alive")

	if method == "POST" || method == "PUT" {
		req.Header.Add("Content-Type", "application/json;charset='utf-8'")
	}
	req.Header.Add("User-Agent", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31")
	for key, value := range headers {
		req.Header.Add(key, value)
	}
	resp, err2 := client.Do(req)
	if err2 == nil {
		defer resp.Body.Close()

		body, _ := ioutil.ReadAll(resp.Body)
		return body, nil
	} else {
		return nil, err2
	}
}

func GetAccessToken() error {
	params := map[string]interface{}{
		"duration_seconds": 86399,
		"grant_type":       "urn:ietf:params:oauth:grant-type:jwt-bearer",
	}

	header := map[string]string{
		// "Content-Type":  "application/json",
		"Authorization": "Bearer " + GetToken(),
	}
	body, err := NewCurrencyRequest(http.MethodPost, "https://api.coze.cn/api/permission/oauth2/token", params, header)

	if err != nil {
		return err
	}
	object, _ := gabs.ParseJSON(body)
	fmt.Println("object", object)
	return errors.New("未获取到内容")
}

func MainCoze() {
	err := GetAccessToken()
	if err != nil {
		fmt.Println(err)
	}
}
